home *** CD-ROM | disk | FTP | other *** search
- #ifdef UNIX
- /*
- * Session manager and session manager switch
- *
- * The session manager switch intercepts all session and console I/O calls and
- * forwards them to session managers based on the switch entry managing the
- * session, or the system default session manager for new sessions. New
- * sessions may also be started attached to specific session managers.
- * Sessions can also be "reparented" from one session manager to another.
- *
- * Per-session options are now supported. Per-session-*manager* options have
- * assigned slots in the session manager definition, but are not yet supported.
- */
-
- #include "global.h"
- #include "commands.h"
- #include <signal.h>
- #include "hardware.h"
- #include "proc.h"
- #include "socket.h"
- #undef tputs
- #include "tty.h"
- #include "sessmgr.h"
-
- #if !defined(_lint)
- static char rcsid[] OPTIONAL = "$Id: sessmgr.c,v 1.20 1997/07/31 00:44:20 root Exp root $";
- #endif
-
- static int dosmstatus (int, char **, void *);
- static int dosmdefault (int, char **, void *);
- static int dosmcreate (int, char **, void *);
- static int dosmreparent (int, char **, void *);
- static int dosmoptions (int, char **, void *);
-
- void sm_status (int pos, char *str);
- extern void displayStatLine (int offset, int phase, int onlymarquee);
- extern int Numrows;
- extern int BLOCKStatline, INStatline;
-
-
- /*
- * The session manager switch: an array of pointers to session managers.
- */
-
- #ifdef SM_CURSES
- extern struct sessmgr_sw curses_sessmgr;
- #endif
- #ifdef SM_RAW
- extern struct sessmgr_sw raw_sessmgr;
- #endif
- #ifdef SM_DUMB
- extern struct sessmgr_sw dumb_sessmgr;
- #endif
-
- static struct sessmgr_sw *sessmgr_sw[] =
- {
- #ifdef SM_CURSES
- &curses_sessmgr,
- #endif
- #ifdef SM_DUMB
- &dumb_sessmgr,
- #endif
- #ifdef SM_RAW
- &raw_sessmgr,
- #endif
- 0,
- };
-
-
-
- static int sesm_initted;
-
- /*
- * Commands for session manager administration
- */
-
- static struct cmds SMcmds[] =
- {
- { "create", dosmcreate, 0, 0, NULLCHAR },
- { "default", dosmdefault, 0, 0, NULLCHAR },
- { "options", dosmoptions, 0, 0, NULLCHAR },
- { "reparent", dosmreparent, 0, 0, NULLCHAR },
- { "status", dosmstatus, 0, 0, NULLCHAR },
- { NULLCHAR, NULLFP ((int, char **, void *)),0, 0, NULLCHAR }
- };
-
-
- static struct cmds SMsessions[] =
- {
- #ifdef MAILBOX
- { "bbs", dobbs, 1024, 0, NULLCHAR },
- #endif
- #ifdef AX25
- #ifdef ALLSESSIONS
- { "connect", doconnect, 1024, 3, "connect <interface> <callsign>" },
- #endif
- #endif
- #ifdef ALLCMD
- { "dir", dodir, 0, 0, NULLCHAR },
- #endif
- #ifdef DIALER
- { "dialer", dodialer, 512, 2, "dialer <iface> [<file> [<seconds> [<pings> [<hostid>]]]]" },
- #endif
- #ifdef ALLCMD
- { "finger", dofinger, 1024, 2, "finger name[@host]" },
- #endif
- #ifdef ALLSESSIONS
- { "ftp", doftp, 2048, 2, "ftp <address>" },
- #endif
- #ifdef ALLCMD
- { "more", domore, 0, 2, "more <file> [searchstring]" },
- #endif
- { "ping", doping, 512, 4, "ping <hostid> <length> <interval> [incflag]" },
- #ifdef RLOGINCLI
- { "rlogin", dorlogin, 2048, 2, "rlogin <address>" },
- #endif
- #if defined(AX25) && defined(ALLSESSIONS) && defined(ALLSERV)
- { "split", doconnect, 1024, 3, "split <interface> <callsign>" },
- #endif
- #ifdef ALLSESSIONS
- { "telnet", dotelnet, 1024, 2, "telnet <address> [port]" },
- #endif
- #ifdef ALLSERV
- { "ttylink", dotelnet, 1024, 2, "ttylink <address> [port]" },
- #endif
- { NULLCHAR, NULLFP ((int, char **, void *)),
- 0, 0, NULLCHAR },
- };
-
- #if 0
- extern int STATLINE;
- #endif
-
-
-
- /*
- * Used by the newscreen() entry point, the creation of the trace session
- * in main(), and by reparenting.
- */
-
- static void
- sm_newscreen (const char *sc, struct session *sp)
- {
- struct sessmgr_sw *sm;
- const char *cp;
-
- if ((sm = sm_lookup (sc, &cp)) == (struct sessmgr_sw *) 0) {
- sm = sessmgr_sw[0]; /* system-wide default session manager */
- cp = 0;
- }
- if (!sp)
- return;
- sp->screen = mallocw (sizeof *sp->screen);
- if (!(sm->flags & SM_INIT)) {
- if (Current && Current != sp && Current->screen &&
- !(Current->screen->sessmgr->flags & SM_SUSPEND)) {
- (*Current->screen->sessmgr->suspend) (Current->screen->sessmgr);
- Current->screen->sessmgr->flags |= SM_SUSPEND;
- }
- (void) (*sm->init) (sm);
- sm->flags |= SM_INIT;
- }
- sm->refcnt++;
- sp->screen->sessmgr = sm;
- sp->screen->sesmdat =
- (*sm->create) (sm, sp);
- if (sm->sessopt && cp)
- (void) (*sm->sessopt) (sm, sp->screen->sesmdat, cp);
- sp->screen->flags = 0;
- #if 0
- sp->screen->statline = STATLINE;
- #else
- sp->screen->statline = 0;
- #endif
- if (sp->split)
- sp->screen->flags |= SMS_SPLIT;
- if (!(sm->flags & SM_SPLIT))
- sp->split = 0; /* if sm can't do split, split sessions are deranged */
- sp->screen->next_sm = strdup (sc);
- sp->screen->use_sm = sp->screen->next_sm;
- if (sm->flags & SM_SUSPEND) {
- (*Current->screen->sessmgr->resume) (Current->screen->sessmgr);
- Current->screen->sessmgr->flags &= ~SM_SUSPEND;
- }
- #if 0
- /* this is ugly... */
- /* (it's also wrong; figure it out later...) */
- if (sp->type == TRACESESSION)
- sp->screen->flags |= SMS_DISCARD;
- #endif
- }
-
-
-
- int
- dosessmgr (int argc, char **argv, void *p)
- {
- if (argc < 2)
- return dosmstatus (argc, argv, p);
- return subcmd (SMcmds, argc, argv, p);
- }
-
-
-
- int
- dosmstatus (int argc OPTIONAL, char **argv OPTIONAL, void *p OPTIONAL)
- {
- struct screen *sp;
- char *cp;
- int s;
-
- tprintf ("Known session managers are:\n");
- for (s = 0; sessmgr_sw[s]; s++)
- tprintf ("%s\n", sessmgr_sw[s]->name);
- tprintf ("\n");
- (void) dosmdefault (0, 0, 0);
- tprintf ("\n# Type Name Process Manager Options\n");
- tprintf ("== ============ ============ ============ ======== ==========\n");
- for (s = 0; (unsigned) s < Nsessions; s++) {
- if (Sessions[s].type == FREE)
- continue;
- tprintf ("%-2d %-12s ", s, Sestypes[Sessions[s].type]);
- if (Sessions[s].name)
- tprintf ("%-12.12s ", Sessions[s].name);
- else
- tprintf (" ");
- if (Sessions[s].proc->name && *Sessions[s].proc->name)
- tprintf ("%-12.12s", Sessions[s].proc->name);
- else
- tprintf ("%8.8lx ", (uint32) Sessions[s].proc);
- tprintf (" %-8.8s", Sessions[s].screen->sessmgr->name);
- /* we don't support session MANAGER options just yet... */
- if ((sp = Sessions[s].screen)->sessmgr->sessopt &&
- (cp = (*sp->sessmgr->sessopt) (sp->sessmgr, sp->sesmdat, (char *) 0)) != NULLCHAR)
- tprintf (" %s", cp);
- tprintf ("\n");
- }
- return 0;
- }
-
-
-
- int
- dosmdefault (int argc, char **argv, void *p OPTIONAL)
- {
- char const *cp;
-
- if (argc < 2) {
- if (Current && Current->screen && Current->type == COMMAND)
- cp = Current->screen->next_sm;
- else if (Command && Command->screen)
- cp = Command->screen->next_sm;
- else
- cp = "";
- if (!cp || !*cp)
- cp = sessmgr_sw[0]->name;
- tprintf ("Session manager for new sessions is \"%s\".\n", cp);
- return 0;
- }
- if (argc > 2) {
- tprintf ("usage: sessmgr default [session-manager]\n");
- return 1;
- }
- if (!sm_lookup (argv[1], 0)) {
- tprintf ("No such session manager: \"%s\"\n", argv[1]);
- return 1;
- }
- if (Current->screen->next_sm)
- free (Current->screen->next_sm);
- Current->screen->next_sm = strdup (argv[1]);
- return 0;
- }
-
-
-
- int
- dosmcreate (int argc, char **argv, void *p)
- {
- int rc;
-
- if (argc < 3) {
- tprintf ("usage: sessmgr create session-manager command [args...]\n");
- return 1;
- }
- if (!sm_lookup (argv[1], 0)) {
- tprintf ("Unknown session manager \"%s\"\n", argv[1]);
- return 1;
- }
- if (Current->type != COMMAND)
- write (2, "WHOA! I'm not being run from a COMMAND session!\n", 48);
- Current->screen->use_sm = argv[1];
- rc = subcmd (SMsessions, argc - 1, argv + 1, p);
- return rc;
- }
-
-
-
- int
- dosmoptions (int argc, char **argv, void *p OPTIONAL)
- {
- struct screen *sp;
- char *cp;
- int i;
-
- if (argc < 2) {
- tprintf ("usage: sessmgr options session [options]\n");
- return 1;
- }
- if ((i = atoi (argv[1])) < 0 || (unsigned) i > Nsessions || Sessions[i].type == FREE) {
- tprintf ("Invalid session %s\n", argv[1]);
- return 1;
- }
- sp = Sessions[i].screen;
- if (argc < 3) {
- tprintf ("Options for session: ");
- if (!sp->sessmgr->sessopt)
- cp = 0;
- else
- cp = (*sp->sessmgr->sessopt) (sp->sessmgr, sp->sesmdat, (char *) 0);
- if (!cp)
- tprintf ("(none)\n");
- else
- tprintf ("%s\n", cp);
- return 0;
- }
- if (sp->sessmgr->sessopt)
- (void) (*sp->sessmgr->sessopt) (sp->sessmgr, sp->sesmdat, argv[2]);
- return 0;
- }
-
-
-
- /*
- * Administration of the session manager interface
- */
-
- struct sessmgr_sw *
- sm_lookup (const char *smname, const char **optp)
- {
- static char buf[1024];
- char const *cp;
- int i;
-
- if (!smname) {
- /* inherit a reasonable session manager */
- if (Current && Current->screen && Current->type == COMMAND) {
- smname = Current->screen->use_sm;
- Current->screen->use_sm = Current->screen->next_sm;
- } else if (Command && Command->screen)
- smname = Command->screen->next_sm;
- else
- smname = "";
- }
-
- for (i = 0, cp = smname; i < 1024 && *cp && *cp != ':'; cp++)
- buf[i++] = *cp;
-
- /*lint -save -e661 */
- if (i < 1024)
- buf[i] = '\0';
- /*lint -restore */
- if (*cp)
- cp++;
- else
- cp = 0;
-
- if (!i) {
- if (optp) /* is this wise? sessmgr ":opt", that is */
- *optp = cp;
- return sessmgr_sw[0];
- }
- for (i = 0; sessmgr_sw[i]; i++) {
- if (strcasecmp (sessmgr_sw[i]->name, buf) == 0) {
- if (optp)
- *optp = cp;
- return sessmgr_sw[i];
- }
- }
- if (optp)
- *optp = 0;
- return 0;
- }
-
-
-
- int
- sm_blocked (struct session *sp)
- {
- /* Return TRUE if the session is blocked. */
- return !(sp->screen->flags & SMS_ACTIVE) ||
- (sp->screen->sessmgr->flags & SM_SUSPEND);
- }
-
-
-
- /*
- * Session reparenting. This is mildly interesting.
- *
- * The idea is that a session can be destroyed and recreated. (Actually, the
- * session is retained; the screen is destroyed.) The only fly in the oint-
- * ment is that you can't retain the contents of the screen: some session
- * managers have no backing store ("dumb", and especially "none").
- *
- * Sessions can be reparented individually or by session manager. Individual
- * sessions can be named if they have names.
- */
-
- static void
- sm_reparent (struct session *sp, char *new)
- {
- struct sessmgr_sw *old, *np;
- int susp;
-
- if ((np = sm_lookup (new, 0)) == (struct sessmgr_sw *) 0)
- return;
- if ((old = sp->screen->sessmgr) == np)
- return;
- if (sp->screen->flags & SMS_SPLIT) /* sp->split is 0 if s.m. won't split */
- sp->split = 1; /* newscreen will deactivate if needed */
- susp = (old->flags & SM_STDIO) && (np->flags & SM_STDIO);
- freescreen (sp);
- if (susp && !(old->flags & SM_SUSPEND)) {
- (*old->suspend) (old);
- old->flags |= SM_SUSPEND;
- }
- sm_newscreen (new, sp);
- }
-
-
-
- int
- dosmreparent (int argc, char **argv, void *p OPTIONAL)
- {
- struct sessmgr_sw *old;
- struct session *s;
- int i, susp;
-
- if (argc != 3) {
- tprintf ("usage: sessmgr reparent <session> <session-manager>\n");
- return 1;
- }
- if (!sm_lookup (argv[2], 0)) {
- tprintf ("Unknown session manager \"%s\"\n", argv[2]);
- return -1;
- }
- if (isdigit (argv[1][0])) {
- if ((unsigned) (i = atoi (argv[1])) >= Nsessions || Sessions[i].type == FREE) {
- tprintf ("Invalid session number %d.\n", i);
- return 1;
- }
- sm_reparent (Sessions + i, argv[2]);
- if (Sessions + i == Current)
- Sessions[i].screen->flags |= SMS_ACTIVE;
- else {
- /* we must do this because newscreen() partially switches us */
- swapscreen (Current, Sessions + i);
- swapscreen (Sessions + i, Current);
- }
- return 0;
- }
- susp = -1;
- for (i = 0; (unsigned) i < Nsessions; i++) {
- if (Sessions[i].type == FREE)
- continue;
- if (Sessions[i].name && *Sessions[i].name &&
- strcasecmp (Sessions[i].name, argv[1]) == 0) {
- if (susp != -1)
- break;
- susp = i;
- }
- if (Sessions[i].proc->name && *Sessions[i].proc->name &&
- strcasecmp (Sessions[i].proc->name, argv[1]) == 0) {
- if (susp != -1)
- break;
- susp = i;
- }
- if (strcasecmp (Sestypes[Sessions[i].type], argv[1]) == 0) {
- if (susp != -1)
- break;
- susp = i;
- }
- }
- if ((unsigned) i != Nsessions) {
- tprintf ("Session ID \"%s\" is not unique\n", argv[1]);
- return 1;
- }
- if (susp != -1) {
- sm_reparent (Sessions + susp, argv[2]);
- if (Sessions + susp == Current)
- Sessions[susp].screen->flags |= SMS_ACTIVE;
- else {
- /* we must do this because newscreen() partially switches us */
- swapscreen (Current, Sessions + susp);
- swapscreen (Sessions + susp, Current);
- }
- return 0;
- }
- for (i = 0; sessmgr_sw[i]; i++) {
- if (sessmgr_sw[i]->refcnt && strcasecmp (sessmgr_sw[i]->name, argv[1]) == 0)
- break;
- }
- if (!sessmgr_sw[i]) {
- tprintf ("Can't decipher session ID \"%s\"\n", argv[1]);
- return 1;
- }
- /* reparent all of them! */
- old = sessmgr_sw[i];
- s = Current;
- for (i = 0; (unsigned) i < Nsessions; i++) {
- if (Sessions[i].screen->sessmgr != old)
- continue;
- sm_reparent (Sessions + i, argv[2]);
- swapscreen (s, Sessions + i);
- s = Sessions + i;
- }
- if (s == Current)
- Sessions[i].screen->flags |= SMS_ACTIVE;
- else
- swapscreen (s, Current);
- return 0;
- }
-
-
-
- /*
- * Ugly hack for doshell(): tell if the current session manager is SM_STDIO.
- */
-
- int
- sm_usestdio (void)
- {
- return Current->screen->sessmgr->flags & SM_STDIO;
- }
-
-
-
- /*
- * Start a session with a specified session manager. This could be static
- * since it's normally only used by the "sessmgr <sm> create" command, but
- * we also need it to start the trace session in a different session manager
- * from the default.
- *
- * This incorporates newsession(). Ultimately, newsession() should be changed
- * to call this function.
- */
-
- struct session *
- sm_newsession (const char *sc, const char *name, int type, int split)
- {
- struct session *sp;
- int i;
-
- if (!sc || !*sc) {
- /*
- * HACK - new sessions should inherit the current session if it is a
- * COMMAND session. Else use Command's next session, unless Command
- * doesn't exist yet (creation of Command or Trace) in which case the
- * default session manager is used.
- *
- * Maybe this isn't really a hack... but it feels like one.
- */
- if (Current && Current->screen && Current->type == COMMAND)
- sc = Current->screen->next_sm;
- else if (Command && Command->screen)
- sc = Command->screen->next_sm;
- else
- sc = "";
- }
- if (type == TRACESESSION)
- i = (int) (Nsessions - 1);
- else {
- for (i = 0; (unsigned) i < Nsessions; i++) {
- if (Sessions[i].type == FREE)
- break;
- }
- }
- if ((unsigned) i == Nsessions)
- return NULLSESSION;
- sp = Sessions + i;
- sp->type = type;
- sp->s = -1;
- if (name != NULLCHAR)
- sp->name = strdup (name);
- sp->proc = Curproc;
- /* update Curproc's session pointer as well! */
- /* (in theory this could leave a dangling session...?) */
- Curproc->session = sp;
- /* Create standard input and output sockets. Output is
- * translated to local end-of-line by default
- */
- Curproc->input = sp->input = socket (AF_LOCAL, SOCK_STREAM, 0);
- (void) seteol (Curproc->input, Eol);
- (void) sockmode (Curproc->input, SOCK_BINARY);
- Curproc->output = sp->output = socket (AF_LOCAL, SOCK_STREAM, 0);
- (void) seteol (Curproc->output, Eol);
- (void) sockmode (Curproc->output, SOCK_ASCII);
- /* on by default */
- sp->ttystate.crnl = sp->ttystate.edit = sp->ttystate.echo = 1;
- sp->flowmode = 0; /* Off by default */
- sp->row = Numrows;
- sp->morewait = 0;
- sp->split = split;
- sp->tsavex = sp->tsavey = 1;
- sm_newscreen (sc, sp);
- swapscreen (Current, sp);
- Current = sp;
- return sp;
- }
-
-
-
- /*
- * Session manager initiation and cleanup.
- */
-
- void
- ioinit (int no_itimer)
- {
- init_sys (no_itimer);
- sesm_initted = 1;
- }
-
-
-
- void
- iostop (void)
- {
- int c;
-
- sesm_initted = 0;
- for (c = 0; sessmgr_sw[c]; c++) {
- if (sessmgr_sw[c]->flags & SM_INIT)
- (*sessmgr_sw[c]->end) (sessmgr_sw[c]);
- }
- deinit_sys ();
- }
-
-
-
- /*
- * Suspend and resume now only suspend/resume the current session manager.
- * It is assumed that the session manger is SM_STDIO and that an outside
- * process needs to intercept the SM_STDIO interface temporarily.
- */
-
- void
- iosuspend (void)
- {
- register struct screen *sp = Current->screen;
-
- if ((sp->sessmgr->flags & (SM_INIT | SM_SUSPEND)) == SM_INIT) {
- (*sp->sessmgr->suspend) (sp->sessmgr);
- sp->sessmgr->flags |= SM_SUSPEND;
- }
- }
-
-
-
- void
- ioresume (void)
- {
- register struct screen *sp = Current->screen;
-
- if ((sp->sessmgr->flags & (SM_INIT | SM_SUSPEND)) == (SM_INIT | SM_SUSPEND)) {
- (*sp->sessmgr->resume) (sp->sessmgr);
- sp->sessmgr->flags &= ~SM_SUSPEND;
- }
- }
-
-
-
- /*
- * Session creation, destruction, and swapping.
- */
-
- void
- j_newscreen (struct session *sp)
- {
- char const *sc;
-
- if (Current && Current->screen && Current->type == COMMAND) {
- sc = Current->screen->use_sm;
- Current->screen->use_sm = Current->screen->next_sm;
- } else if (Command && Command->screen)
- sc = Command->screen->next_sm;
- else
- sc = "";
- sm_newscreen (sc, sp);
- }
-
-
-
- void
- freescreen (struct session *sp)
- {
- if (!sp || !sp->screen)
- return;
- (*sp->screen->sessmgr->destroy) (sp->screen->sessmgr, sp->screen->sesmdat);
- free (sp->screen->next_sm);
- if (!--sp->screen->sessmgr->refcnt) {
- (*sp->screen->sessmgr->end) (sp->screen->sessmgr);
- sp->screen->sessmgr->flags &= ~SM_INIT;
- }
- free (sp->screen);
- sp->screen = 0;
- }
-
- extern struct session *ScreenOwner; /* Session currently displayed */
-
-
-
- void
- swapscreen (struct session *old, struct session *new)
- {
- if (old == new)
- return;
- #if 1
- BLOCKStatline += 1;
- #endif
- #if 1
- while (INStatline)
- kwait (NULL);
- #endif
- /*
- * If they're in different session managers, swap each to/from NULL.
- * Otherwise, swap them in the common session manager.
- */
- if (old && new && old->screen->sessmgr == new->screen->sessmgr) {
- if (!(*old->screen->sessmgr->swtch) (old->screen->sessmgr,
- old->screen->sesmdat, new->screen->sesmdat))
- old->screen->flags &= ~SMS_ACTIVE;
- } else {
- if (old)
- (void) (*old->screen->sessmgr->swtch) (old->screen->sessmgr, old->screen->sesmdat, 0);
-
- if (old && new && (old->screen->sessmgr->flags & SM_STDIO) &&
- (new->screen->sessmgr->flags & SM_STDIO) &&
- !(old->screen->sessmgr->flags & SM_SUSPEND)) {
- (*old->screen->sessmgr->suspend) (old->screen->sessmgr);
- old->screen->sessmgr->flags |= SM_SUSPEND;
- }
- if (new &&
- ((new->screen->sessmgr->flags & (SM_SUSPEND | SM_STDIO | SM_INIT)) ==
- (SM_SUSPEND | SM_STDIO | SM_INIT))) {
- (*new->screen->sessmgr->resume) (new->screen->sessmgr);
- new->screen->sessmgr->flags &= ~SM_SUSPEND;
- }
- if (new)
- (void) (*new->screen->sessmgr->swtch) (new->screen->sessmgr, 0, new->screen->sesmdat);
- }
- ScreenOwner = new;
- #if 1
- BLOCKStatline -= 1;
- #endif
- if (new) {
- new->screen->flags |= SMS_ACTIVE;
- #if 1
- displayStatLine (0, 1, 0);
- #endif
- ksignal (new->screen, 0);
- }
- }
-
-
-
- /*
- * Some session managers (e.g. curses) aren't re-entrant. We deal with this
- * by locking individual screens. (we assume the session manager is reentrant
- * between separate screens; this may be unsafe...)
- */
-
- static int
- LOCKSCR (register struct screen *sc, int wait)
- {
- sigset_t s, t;
-
- (void) sigfillset (&s);
- (void) sigprocmask (SIG_BLOCK, &s, &t);
- while (sc->flags & SM_LOCK) {
- if (!wait)
- return 0;
- kwait (&sc->flags);
- }
- sc->flags |= SM_LOCK;
- (void) sigprocmask (SIG_SETMASK, &t, 0);
- return 1;
- }
-
-
-
- static void
- UNLOCKSCR (register struct screen *sc)
- {
- sigset_t s, t;
-
- (void) sigfillset (&s);
- (void) sigprocmask (SIG_BLOCK, &s, &t);
- sc->flags &= ~SM_LOCK;
- ksignal (&sc->flags, 0);
- (void) sigprocmask (SIG_SETMASK, &t, 0);
- }
-
-
-
- /*
- * I/O routines come in two flavors. The internal ones, which start with
- * "s", are used by rflush() and by the external ones. The external ones are
- * used by the rest of NOS.
- */
-
- static void
- sputch (struct session *s, int c)
- {
- (*s->screen->sessmgr->putch) (s->screen->sessmgr, s->screen->sesmdat, c);
- }
-
-
-
- static void
- scputs (struct session *s, const char *str)
- {
- register struct screen *sp;
-
- sp = s->screen;
- while (*str)
- (*sp->sessmgr->putch) (sp->sessmgr, sp->sesmdat, *str++);
- }
-
-
-
- static void
- sclreol (struct session *s)
- {
- (*s->screen->sessmgr->clreol) (s->screen->sessmgr, s->screen->sesmdat);
- }
-
-
-
- /*
- * rflush() used to flush data to the display process. Now it does I/O itself;
- * the display process is defunct.
- */
-
- void
- rflush (void)
- {
- struct session *sp;
- int i, c, statsize;
-
- if (!Sessions || !sesm_initted)
- return; /* timer could tick before we exist, or while suspended */
- #ifdef SCREENSAVER
- if (!ssenabled ())
- #endif
- {
- for (sp = Sessions, i = 0; (unsigned) i < Nsessions; sp++, i++) {
- if (sp->type == FREE)
- continue;
- if (!sp->screen || !sp->screen->sessmgr || !sp->screen->sesmdat)
- continue;
- if (!(sp->screen->flags & SMS_ACTIVE) || sp->morewait == 1)
- continue;
- /* err, do I want to do this? */
- if (sp->screen->sessmgr->flags & SM_SUSPEND)
- continue;
- #ifdef SCREENSAVER
- if (ssenabled ())
- continue;
- #endif
-
- if (!LOCKSCR (sp->screen, 0)) {
- write (2, "screen not responding - still trying\r\n", 38);
- continue;
- }
- (*sp->screen->sessmgr->rflush) (sp->screen->sessmgr,
- sp->screen->sesmdat);
- if (sp->morewait == 2) {
- sp->morewait = 0;
- sputch (sp, '\r');
- sclreol (sp);
- }
- while (socklen (sp->output, 0) > 0) {
- if ((c = rrecvchar (sp->output)) == EOF)
- continue;
- if (!sp->split || c != 0x0a)
- sputch (sp, c);
- else {
- scputs (sp, Eol);
- sclreol (sp);
- }
- if (sp->record != NULLFILE) {
- if (c == '\r' || c == '\n')
- (void) fflush (sp->record);
- if (c != '\r' || sockmode (sp->output, -1) != SOCK_ASCII)
- (void) putc (c, sp->record);
- }
- statsize = 0;
- if (sp->screen->statline)
- statsize = ((sp == Command) ? getStatlines() : 1);
-
- if (sp->flowmode && c == '\n' && sp->row > 0 && --sp->row == statsize) {
- scputs (sp, "--More--");
- sp->morewait = 1;
- sp->row = 0;
- break;
- }
- }
- (*sp->screen->sessmgr->flush) (sp->screen->sessmgr, sp->screen->sesmdat);
- UNLOCKSCR (sp->screen);
- }
- }
- }
-
-
-
- /*
- * Public output routines. getcursess() attempts to intuit the correct session
- * for output.
- */
-
- static struct session *
- getcursess (void)
- {
- static struct proc *kbproc = NULLPROC;
-
- /* this is a horrible hack that will (MUST!) go away in the future */
- if (!kbproc && Curproc && strcmp (Curproc->name, "keyboard") == 0)
- kbproc = Curproc;
- if (kbproc == Curproc)
- return Current;
- /*
- * if Curproc's session isn't active we must block...
- * N.B. should handle trace with a special flag indicating that the
- * session should discard output instead of blocking
- */
- if (!(Curproc->session->screen->flags & SMS_ACTIVE)) {
- #if 0
- if (Curproc->session->screen->flags & SMS_DISCARD)
- return 0;
- #endif
- kwait (Current->screen);
- }
- #if 1
- return Current;
- #else
- return Curproc->session;
- #endif
- }
-
-
-
- void
- putch (int c)
- {
- struct session *sp;
-
- sp = getcursess ();
- (void) LOCKSCR (sp->screen, 1);
- sputch (sp, c);
- UNLOCKSCR (sp->screen);
- }
-
-
-
- void
- cputs (const char *s)
- {
- struct session *sp;
-
- sp = getcursess ();
- (void) LOCKSCR (sp->screen, 1);
- scputs (sp, s);
- UNLOCKSCR (sp->screen);
- }
-
-
-
- void
- clreol (void)
- {
- struct session *sp;
-
- sp = getcursess ();
- (void) LOCKSCR (sp->screen, 1);
- sclreol (sp);
- UNLOCKSCR (sp->screen);
- }
-
-
-
- void
- clrscr (void)
- {
- register struct screen *sp;
-
- sp = getcursess ()->screen;
- (void) LOCKSCR (sp, 1);
- (*sp->sessmgr->clrscr) (sp->sessmgr, sp->sesmdat);
- UNLOCKSCR (sp);
- }
-
-
-
- int
- wherex (void)
- {
- register struct screen *sp;
- int i;
-
- sp = getcursess ()->screen;
- if (sp->sessmgr->wherex) {
- (void) LOCKSCR (sp, 1);
- i = (*sp->sessmgr->wherex) (sp->sessmgr, sp->sesmdat);
- UNLOCKSCR (sp);
- return i;
- }
- return -1;
- }
-
-
-
- int
- wherey (void)
- {
- register struct screen *sp;
- int i;
-
- sp = getcursess ()->screen;
- if (sp->sessmgr->wherey) {
- (void) LOCKSCR (sp, 1);
- i = (*sp->sessmgr->wherey) (sp->sessmgr, sp->sesmdat);
- UNLOCKSCR (sp);
- return i;
- }
- return -1;
- }
-
-
-
- void
- window (int x1, int y1, int x2, int y2)
- {
- register struct screen *sp;
-
- sp = getcursess ()->screen;
- if (sp->sessmgr->window) {
- (void) LOCKSCR (sp, 1);
- (*sp->sessmgr->window) (sp->sessmgr, sp->sesmdat, x1, y1, x2, y2);
- UNLOCKSCR (sp);
- }
- }
-
-
-
- void
- gotoxy (int x, int y)
- {
- register struct screen *sp;
-
- sp = getcursess ()->screen;
- (void) LOCKSCR (sp, 1);
- (*sp->sessmgr->gotoxy) (sp->sessmgr, sp->sesmdat, x, y);
- UNLOCKSCR (sp);
- }
-
-
-
- void
- highvideo (void)
- {
- register struct screen *sp;
-
- sp = getcursess ()->screen;
- (void) LOCKSCR (sp, 1);
- (*sp->sessmgr->high) (sp->sessmgr, sp->sesmdat);
- UNLOCKSCR (sp);
- }
-
-
-
- void
- normvideo (void)
- {
- register struct screen *sp;
-
- sp = getcursess ()->screen;
- (void) LOCKSCR (sp, 1);
- (*sp->sessmgr->norm) (sp->sessmgr, sp->sesmdat);
- UNLOCKSCR (sp);
- }
-
-
- void
- textbackground (int color)
- {
- register struct screen *sp;
-
- sp = getcursess ()->screen;
- (void) LOCKSCR (sp, 1);
- (*sp->sessmgr->bground) (sp->sessmgr, sp->sesmdat, color);
- UNLOCKSCR (sp);
- }
-
-
- void
- textcolor (int color)
- {
- register struct screen *sp;
-
- sp = getcursess ()->screen;
- (void) LOCKSCR (sp, 1);
- (*sp->sessmgr->fground) (sp->sessmgr, sp->sesmdat, color);
- UNLOCKSCR (sp);
- }
-
-
- void
- textattr (int color)
- {
- register struct screen *sp;
-
- sp = getcursess ()->screen;
- (void) LOCKSCR (sp, 1);
- (*sp->sessmgr->txtattr) (sp->sessmgr, sp->sesmdat, color);
- UNLOCKSCR (sp);
- }
-
-
- void
- textrefresh (void)
- {
- register struct screen *sp;
-
- sp = getcursess ()->screen;
- (void) LOCKSCR (sp, 1);
- (*sp->sessmgr->refresh) (sp->sessmgr, sp->sesmdat);
- UNLOCKSCR (sp);
- }
-
-
- void
- _setcursortype (int t)
- {
- register struct screen *sp;
-
- sp = getcursess ()->screen;
- if (sp->sessmgr->cursor) {
- (void) LOCKSCR (sp, 1);
- (*sp->sessmgr->cursor) (sp->sessmgr, sp->sesmdat, t);
- UNLOCKSCR (sp);
- }
- }
-
-
-
- int
- kbread (void)
- {
- register struct screen *sp;
-
- sp = getcursess ()->screen;
- return (*sp->sessmgr->kbread) (sp->sessmgr, sp->sesmdat);
- }
-
-
-
- /*
- * The status entry point is different: any routine may call the status output
- * routine, which calls the status switch entry for the Command screen. If
- * that is NULL, we perform direct output without passing information to
- * rflush(); this avoids the flow control problems which have plagued previous
- * versions, although it requires that we duplicate parts of rflush() here
- * (and it's ugly).
- *
- * The numeric argument is presently ignored. Eventually I may use it for
- * a positioning hint.
- */
-
- void
- sm_status (int pos, char *str)
- {
- struct screen *cs;
-
- cs = Command->screen;
- if (cs->sessmgr->status)
- (*cs->sessmgr->status) (cs->sessmgr, cs->sesmdat, pos, str);
- else {
- if (cs->sessmgr->flags & SM_SUSPEND)
- return;
- if (!(cs->flags & SMS_ACTIVE))
- return;
- (void) LOCKSCR (cs, 1);
- (*cs->sessmgr->rflush) (cs->sessmgr, cs->sesmdat);
- /* should translate \n to Eol */
- scputs (Command, str);
- #if 0
- scputs (Command, Eol);
- #endif
- (*cs->sessmgr->flush) (cs->sessmgr, cs->sesmdat);
- UNLOCKSCR (cs);
- }
- }
-
- #endif /* UNIX */
-